home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 58 / pcpp58a.iso / extras / quake 3 source / Q3A_ToolSource.exe / Main / aselib.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-02  |  19.9 KB  |  913 lines

  1.  
  2. #include "aselib.h"
  3.  
  4. #include <assert.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7.  
  8. #define MAX_ASE_MATERIALS            32
  9. #define MAX_ASE_OBJECTS                64
  10. #define MAX_ASE_ANIMATIONS            32
  11. #define MAX_ASE_ANIMATION_FRAMES    512
  12.  
  13. #define VERBOSE( x ) { if ( ase.verbose ) { printf x ; } }
  14.  
  15. typedef struct
  16. {
  17.     float x, y, z;
  18.     float nx, ny, nz;
  19.     float s, t;
  20. } aseVertex_t;
  21.  
  22. typedef struct
  23. {
  24.     float s, t;
  25. } aseTVertex_t;
  26.  
  27. typedef int aseFace_t[3];
  28.  
  29. typedef struct
  30. {
  31.     int numFaces;
  32.     int numVertexes;
  33.     int numTVertexes;
  34.  
  35.     int timeValue;
  36.  
  37.     aseVertex_t        *vertexes;
  38.     aseTVertex_t    *tvertexes;
  39.     aseFace_t        *faces, *tfaces;
  40.  
  41.     int currentFace, currentVertex;
  42. } aseMesh_t;
  43.  
  44. typedef struct
  45. {
  46.     int            numFrames;
  47.     aseMesh_t    frames[MAX_ASE_ANIMATION_FRAMES];
  48.  
  49.     int           currentFrame;
  50. } aseMeshAnimation_t;
  51.  
  52. typedef struct
  53. {
  54.     char name[128];
  55. } aseMaterial_t;
  56.  
  57. /*
  58. ** contains the animate sequence of a single surface
  59. ** using a single material
  60. */
  61. typedef struct
  62. {
  63.     char name[128];
  64.  
  65.     int materialRef;
  66.     int numAnimations;
  67.  
  68.     aseMeshAnimation_t    anim;
  69.  
  70. } aseGeomObject_t;
  71.  
  72. typedef struct
  73. {
  74.     int                numMaterials;
  75.     aseMaterial_t    materials[MAX_ASE_MATERIALS];
  76.     aseGeomObject_t objects[MAX_ASE_OBJECTS];
  77.  
  78.     char    *buffer;
  79.     char    *curpos;
  80.     int         len;
  81.  
  82.     int            currentObject;
  83.     qboolean    verbose;
  84.     qboolean    grabAnims;
  85.  
  86. } ase_t;
  87.  
  88. static char s_token[1024];
  89. static ase_t ase;
  90.  
  91. static void ASE_Process( void );
  92. static void ASE_FreeGeomObject( int ndx );
  93.  
  94. /*
  95. ** ASE_Load
  96. */
  97. void ASE_Load( const char *filename, qboolean verbose, qboolean grabAnims )
  98. {
  99.     FILE *fp = fopen( filename, "rb" );
  100.  
  101.     if ( !fp )
  102.         Error( "File not found '%s'", filename );
  103.  
  104.     memset( &ase, 0, sizeof( ase ) );
  105.  
  106.     ase.verbose = verbose;
  107.     ase.grabAnims = grabAnims;
  108.     ase.len = Q_filelength( fp );
  109.  
  110.     ase.curpos = ase.buffer = malloc( ase.len );
  111.  
  112.     printf( "Processing '%s'\n", filename );
  113.  
  114.     if ( fread( ase.buffer, ase.len, 1, fp ) != 1 )
  115.     {
  116.         fclose( fp );
  117.         Error( "fread() != -1 for '%s'", filename );
  118.     }
  119.  
  120.     fclose( fp );
  121.  
  122.     ASE_Process();
  123. }
  124.  
  125. /*
  126. ** ASE_Free
  127. */
  128. void ASE_Free( void )
  129. {
  130.     int i;
  131.  
  132.     for ( i = 0; i < ase.currentObject; i++ )
  133.     {
  134.         ASE_FreeGeomObject( i );
  135.     }
  136. }
  137.  
  138. /*
  139. ** ASE_GetNumSurfaces
  140. */
  141. int ASE_GetNumSurfaces( void )
  142. {
  143.     return ase.currentObject;
  144. }
  145.  
  146. /*
  147. ** ASE_GetSurfaceName
  148. */
  149. const char *ASE_GetSurfaceName( int which )
  150. {
  151.     aseGeomObject_t *pObject = &ase.objects[which];
  152.  
  153.     if ( !pObject->anim.numFrames )
  154.         return 0;
  155.  
  156.     return pObject->name;
  157. }
  158.  
  159. /*
  160. ** ASE_GetSurfaceAnimation
  161. **
  162. ** Returns an animation (sequence of polysets)
  163. */
  164. polyset_t *ASE_GetSurfaceAnimation( int which, int *pNumFrames, int skipFrameStart, int skipFrameEnd, int maxFrames )
  165. {
  166.     aseGeomObject_t *pObject = &ase.objects[which];
  167.     polyset_t *psets;
  168.     int numFramesInAnimation;
  169.     int numFramesToKeep;
  170.     int i, f;
  171.  
  172.     if ( !pObject->anim.numFrames )
  173.         return 0;
  174.  
  175.     if ( pObject->anim.numFrames > maxFrames && maxFrames != -1 )
  176.     {
  177.         numFramesInAnimation = maxFrames;
  178.     }
  179.     else 
  180.     {
  181.         numFramesInAnimation = pObject->anim.numFrames;
  182.         if ( maxFrames != -1 )
  183.             printf( "WARNING: ASE_GetSurfaceAnimation maxFrames > numFramesInAnimation\n" );
  184.     }
  185.  
  186.     if ( skipFrameEnd != -1 )
  187.         numFramesToKeep = numFramesInAnimation - ( skipFrameEnd - skipFrameStart + 1 );
  188.     else
  189.         numFramesToKeep = numFramesInAnimation;
  190.  
  191.     *pNumFrames = numFramesToKeep;
  192.  
  193.     psets = calloc( sizeof( polyset_t ) * numFramesToKeep, 1 );
  194.  
  195.     for ( f = 0, i = 0; i < numFramesInAnimation; i++ )
  196.     {
  197.         int t;
  198.         aseMesh_t *pMesh = &pObject->anim.frames[i];
  199.  
  200.         if ( skipFrameStart != -1 )
  201.         {
  202.             if ( i >= skipFrameStart && i <= skipFrameEnd )
  203.                 continue;
  204.         }
  205.  
  206.         strcpy( psets[f].name, pObject->name );
  207.         strcpy( psets[f].materialname, ase.materials[pObject->materialRef].name );
  208.  
  209.         psets[f].triangles = calloc( sizeof( triangle_t ) * pObject->anim.frames[i].numFaces, 1 );
  210.         psets[f].numtriangles = pObject->anim.frames[i].numFaces;
  211.  
  212.         for ( t = 0; t < pObject->anim.frames[i].numFaces; t++ )
  213.         {
  214.             int k;
  215.  
  216.             for ( k = 0; k < 3; k++ )
  217.             {
  218.                 psets[f].triangles[t].verts[k][0] = pMesh->vertexes[pMesh->faces[t][k]].x;
  219.                 psets[f].triangles[t].verts[k][1] = pMesh->vertexes[pMesh->faces[t][k]].y;
  220.                 psets[f].triangles[t].verts[k][2] = pMesh->vertexes[pMesh->faces[t][k]].z;
  221.  
  222.                 if ( pMesh->tvertexes && pMesh->tfaces )
  223.                 {
  224.                     psets[f].triangles[t].texcoords[k][0] = pMesh->tvertexes[pMesh->tfaces[t][k]].s;
  225.                     psets[f].triangles[t].texcoords[k][1] = pMesh->tvertexes[pMesh->tfaces[t][k]].t;
  226.                 }
  227.  
  228.             }
  229.         }
  230.  
  231.         f++;
  232.     }
  233.  
  234.     return psets;
  235. }
  236.  
  237. static void ASE_FreeGeomObject( int ndx )
  238. {
  239.     aseGeomObject_t *pObject;
  240.     int i;
  241.  
  242.     pObject = &ase.objects[ndx];
  243.  
  244.     for ( i = 0; i < pObject->anim.numFrames; i++ )
  245.     {
  246.         if ( pObject->anim.frames[i].vertexes )
  247.         {
  248.             free( pObject->anim.frames[i].vertexes );
  249.         }
  250.         if ( pObject->anim.frames[i].tvertexes )
  251.         {
  252.             free( pObject->anim.frames[i].tvertexes );
  253.         }
  254.         if ( pObject->anim.frames[i].faces )
  255.         {
  256.             free( pObject->anim.frames[i].faces );
  257.         }
  258.         if ( pObject->anim.frames[i].tfaces )
  259.         {
  260.             free( pObject->anim.frames[i].tfaces );
  261.         }
  262.     }
  263.  
  264.     memset( pObject, 0, sizeof( *pObject ) );
  265. }
  266.  
  267. static aseMesh_t *ASE_GetCurrentMesh( void )
  268. {
  269.     aseGeomObject_t *pObject;
  270.  
  271.     if ( ase.currentObject >= MAX_ASE_OBJECTS )
  272.     {
  273.         Error( "Too many GEOMOBJECTs" );
  274.         return 0; // never called
  275.     }
  276.  
  277.     pObject = &ase.objects[ase.currentObject];
  278.  
  279.     if ( pObject->anim.currentFrame >= MAX_ASE_ANIMATION_FRAMES )
  280.     {
  281.         Error( "Too many MESHes" );
  282.         return 0;
  283.     }
  284.  
  285.     return &pObject->anim.frames[pObject->anim.currentFrame];
  286. }
  287.  
  288. static int CharIsTokenDelimiter( int ch )
  289. {
  290.     if ( ch <= 32 )
  291.         return 1;
  292.     return 0;
  293. }
  294.  
  295. static int ASE_GetToken( qboolean restOfLine )
  296. {
  297.     int i = 0;
  298.  
  299.     if ( ase.buffer == 0 )
  300.         return 0;
  301.  
  302.     if ( ( ase.curpos - ase.buffer ) == ase.len )
  303.         return 0;
  304.  
  305.     // skip over crap
  306.     while ( ( ( ase.curpos - ase.buffer ) < ase.len ) &&
  307.             ( *ase.curpos <= 32 ) )
  308.     {
  309.         ase.curpos++;
  310.     }
  311.  
  312.     while ( ( ase.curpos - ase.buffer ) < ase.len )
  313.     {
  314.         s_token[i] = *ase.curpos;
  315.  
  316.         ase.curpos++;
  317.         i++;
  318.  
  319.         if ( ( CharIsTokenDelimiter( s_token[i-1] ) && !restOfLine ) ||
  320.              ( ( s_token[i-1] == '\n' ) || ( s_token[i-1] == '\r' ) ) )
  321.         {
  322.             s_token[i-1] = 0;
  323.             break;
  324.         }
  325.     }
  326.  
  327.     s_token[i] = 0;
  328.  
  329.     return 1;
  330. }
  331.  
  332. static void ASE_ParseBracedBlock( void (*parser)( const char *token ) )
  333. {
  334.     int indent = 0;
  335.  
  336.     while ( ASE_GetToken( qfalse ) )
  337.     {
  338.         if ( !strcmp( s_token, "{" ) )
  339.         {
  340.             indent++;
  341.         }
  342.         else if ( !strcmp( s_token, "}" ) )
  343.         {
  344.             --indent;
  345.             if ( indent == 0 )
  346.                 break;
  347.             else if ( indent < 0 )
  348.                 Error( "Unexpected '}'" );
  349.         }
  350.         else
  351.         {
  352.             if ( parser )
  353.                 parser( s_token );
  354.         }
  355.     }
  356. }
  357.  
  358. static void ASE_SkipEnclosingBraces( void )
  359. {
  360.     int indent = 0;
  361.  
  362.     while ( ASE_GetToken( qfalse ) )
  363.     {
  364.         if ( !strcmp( s_token, "{" ) )
  365.         {
  366.             indent++;
  367.         }
  368.         else if ( !strcmp( s_token, "}" ) )
  369.         {
  370.             indent--;
  371.             if ( indent == 0 )
  372.                 break;
  373.             else if ( indent < 0 )
  374.                 Error( "Unexpected '}'" );
  375.         }
  376.     }
  377. }
  378.  
  379. static void ASE_SkipRestOfLine( void )
  380. {
  381.     ASE_GetToken( qtrue );
  382. }
  383.  
  384. static void ASE_KeyMAP_DIFFUSE( const char *token )
  385. {
  386.     char buffer[1024], buff1[1024], buff2[1024];
  387.   char *buf1, *buf2;
  388.     int i = 0, count;
  389.  
  390.     if ( !strcmp( token, "*BITMAP" ) )
  391.     {
  392.         ASE_GetToken( qfalse );
  393.  
  394.         strcpy( buffer, s_token + 1 );
  395.         if ( strchr( buffer, '"' ) )
  396.             *strchr( buffer, '"' ) = 0;
  397.  
  398.         while ( buffer[i] )
  399.         {
  400.             if ( buffer[i] == '\\' )
  401.                 buffer[i] = '/';
  402.             i++;
  403.         }
  404.  
  405.     buf1 = buffer;
  406.     buf2 = gamedir;
  407.     // need to compare win32 volumes to potential unix junk
  408.     // 
  409.     if ( (gamedir[1] == ':' && (buffer[0] == '/' && buffer[1] == '/')) ||
  410.       (buffer[1] == ':' && (gamedir[0] == '/' && gamedir[1] == '/')) ) {
  411.       if (buffer[1] == ':') {
  412.         buf1 = buffer + 2;
  413.         buf2 = gamedir + 2;
  414.       } else {
  415.         buf1 = gamedir + 2;
  416.         buf2 = buffer +2;
  417.       }
  418.       count = 0;
  419.       while (*buf2 && count < 2) {
  420.         if (*buf2 == '/') {
  421.           count++;
  422.         }
  423.         buf2++;
  424.       }
  425.     } 
  426.     strcpy(buff1, buf1);
  427.     strlwr(buff1);
  428.     strcpy(buff2, buf2);
  429.     strlwr(buff2);
  430.     if ( strstr( buff2, buff1 + 2 ) )
  431.         {
  432.             strcpy( ase.materials[ase.numMaterials].name, strstr( buff2, buff1 + 2 ) + strlen( buff1 ) - 2 );
  433.         }
  434.         else
  435.         {
  436.             sprintf( ase.materials[ase.numMaterials].name, "(not converted: '%s')", buffer );
  437.             printf( "WARNING: illegal material name '%s'\n", buffer );
  438.         }
  439.     }
  440.     else
  441.     {
  442.     }
  443. }
  444.  
  445. static void ASE_KeyMATERIAL( const char *token )
  446. {
  447.     if ( !strcmp( token, "*MAP_DIFFUSE" ) )
  448.     {
  449.         ASE_ParseBracedBlock( ASE_KeyMAP_DIFFUSE );
  450.     }
  451.     else
  452.     {
  453.     }
  454. }
  455.  
  456. static void ASE_KeyMATERIAL_LIST( const char *token )
  457. {
  458.     if ( !strcmp( token, "*MATERIAL_COUNT" ) )
  459.     {
  460.         ASE_GetToken( qfalse );
  461.         VERBOSE( ( "..num materials: %s\n", s_token ) );
  462.         if ( atoi( s_token ) > MAX_ASE_MATERIALS )
  463.         {
  464.             Error( "Too many materials!" );
  465.         }
  466.         ase.numMaterials = 0;
  467.     }
  468.     else if ( !strcmp( token, "*MATERIAL" ) )
  469.     {
  470.         VERBOSE( ( "..material %d ", ase.numMaterials ) );
  471.         ASE_ParseBracedBlock( ASE_KeyMATERIAL );
  472.         ase.numMaterials++;
  473.     }
  474. }
  475.  
  476. static void ASE_KeyMESH_VERTEX_LIST( const char *token )
  477. {
  478.     aseMesh_t *pMesh = ASE_GetCurrentMesh();
  479.  
  480.     if ( !strcmp( token, "*MESH_VERTEX" ) )
  481.     {
  482.         ASE_GetToken( qfalse );        // skip number
  483.  
  484.         ASE_GetToken( qfalse );
  485.         pMesh->vertexes[pMesh->currentVertex].y = atof( s_token );
  486.  
  487.         ASE_GetToken( qfalse );
  488.         pMesh->vertexes[pMesh->currentVertex].x = -atof( s_token );
  489.  
  490.         ASE_GetToken( qfalse );
  491.         pMesh->vertexes[pMesh->currentVertex].z = atof( s_token );
  492.  
  493.         pMesh->currentVertex++;
  494.  
  495.         if ( pMesh->currentVertex > pMesh->numVertexes )
  496.         {
  497.             Error( "pMesh->currentVertex >= pMesh->numVertexes" );
  498.         }
  499.     }
  500.     else
  501.     {
  502.         Error( "Unknown token '%s' while parsing MESH_VERTEX_LIST", token );
  503.     }
  504. }
  505.  
  506. static void ASE_KeyMESH_FACE_LIST( const char *token )
  507. {
  508.     aseMesh_t *pMesh = ASE_GetCurrentMesh();
  509.  
  510.     if ( !strcmp( token, "*MESH_FACE" ) )
  511.     {
  512.         ASE_GetToken( qfalse );    // skip face number
  513.  
  514.         ASE_GetToken( qfalse );    // skip label
  515.         ASE_GetToken( qfalse );    // first vertex
  516.         pMesh->faces[pMesh->currentFace][0] = atoi( s_token );
  517.  
  518.         ASE_GetToken( qfalse );    // skip label
  519.         ASE_GetToken( qfalse );    // second vertex
  520.         pMesh->faces[pMesh->currentFace][2] = atoi( s_token );
  521.  
  522.         ASE_GetToken( qfalse );    // skip label
  523.         ASE_GetToken( qfalse );    // third vertex
  524.         pMesh->faces[pMesh->currentFace][1] = atoi( s_token );
  525.  
  526.         ASE_GetToken( qtrue );
  527.  
  528. /*
  529.         if ( ( p = strstr( s_token, "*MESH_MTLID" ) ) != 0 )
  530.         {
  531.             p += strlen( "*MESH_MTLID" ) + 1;
  532.             mtlID = atoi( p );
  533.         }
  534.         else
  535.         {
  536.             Error( "No *MESH_MTLID found for face!" );
  537.         }
  538. */
  539.  
  540.         pMesh->currentFace++;
  541.     }
  542.     else
  543.     {
  544.         Error( "Unknown token '%s' while parsing MESH_FACE_LIST", token );
  545.     }
  546. }
  547.  
  548. static void ASE_KeyTFACE_LIST( const char *token )
  549. {
  550.     aseMesh_t *pMesh = ASE_GetCurrentMesh();
  551.  
  552.     if ( !strcmp( token, "*MESH_TFACE" ) )
  553.     {
  554.         int a, b, c;
  555.  
  556.         ASE_GetToken( qfalse );
  557.  
  558.         ASE_GetToken( qfalse );
  559.         a = atoi( s_token );
  560.         ASE_GetToken( qfalse );
  561.         c = atoi( s_token );
  562.         ASE_GetToken( qfalse );
  563.         b = atoi( s_token );
  564.  
  565.         pMesh->tfaces[pMesh->currentFace][0] = a;
  566.         pMesh->tfaces[pMesh->currentFace][1] = b;
  567.         pMesh->tfaces[pMesh->currentFace][2] = c;
  568.  
  569.         pMesh->currentFace++;
  570.     }
  571.     else
  572.     {
  573.         Error( "Unknown token '%s' in MESH_TFACE", token );
  574.     }
  575. }
  576.  
  577. static void ASE_KeyMESH_TVERTLIST( const char *token )
  578. {
  579.     aseMesh_t *pMesh = ASE_GetCurrentMesh();
  580.  
  581.     if ( !strcmp( token, "*MESH_TVERT" ) )
  582.     {
  583.         char u[80], v[80], w[80];
  584.  
  585.         ASE_GetToken( qfalse );
  586.  
  587.         ASE_GetToken( qfalse );
  588.         strcpy( u, s_token );
  589.  
  590.         ASE_GetToken( qfalse );
  591.         strcpy( v, s_token );
  592.  
  593.         ASE_GetToken( qfalse );
  594.         strcpy( w, s_token );
  595.  
  596.         pMesh->tvertexes[pMesh->currentVertex].s = atof( u );
  597.         pMesh->tvertexes[pMesh->currentVertex].t = 1.0f - atof( v );
  598.  
  599.         pMesh->currentVertex++;
  600.  
  601.         if ( pMesh->currentVertex > pMesh->numTVertexes )
  602.         {
  603.             Error( "pMesh->currentVertex > pMesh->numTVertexes" );
  604.         }
  605.     }
  606.     else
  607.     {
  608.         Error( "Unknown token '%s' while parsing MESH_TVERTLIST" );
  609.     }
  610. }
  611.  
  612. static void ASE_KeyMESH( const char *token )
  613. {
  614.     aseMesh_t *pMesh = ASE_GetCurrentMesh();
  615.  
  616.     if ( !strcmp( token, "*TIMEVALUE" ) )
  617.     {
  618.         ASE_GetToken( qfalse );
  619.  
  620.         pMesh->timeValue = atoi( s_token );
  621.         VERBOSE( ( ".....timevalue: %d\n", pMesh->timeValue ) );
  622.     }
  623.     else if ( !strcmp( token, "*MESH_NUMVERTEX" ) )
  624.     {
  625.         ASE_GetToken( qfalse );
  626.  
  627.         pMesh->numVertexes = atoi( s_token );
  628.         VERBOSE( ( ".....TIMEVALUE: %d\n", pMesh->timeValue ) );
  629.         VERBOSE( ( ".....num vertexes: %d\n", pMesh->numVertexes ) );
  630.     }
  631.     else if ( !strcmp( token, "*MESH_NUMFACES" ) )
  632.     {
  633.         ASE_GetToken( qfalse );
  634.  
  635.         pMesh->numFaces = atoi( s_token );
  636.         VERBOSE( ( ".....num faces: %d\n", pMesh->numFaces ) );
  637.     }
  638.     else if ( !strcmp( token, "*MESH_NUMTVFACES" ) )
  639.     {
  640.         ASE_GetToken( qfalse );
  641.  
  642.         if ( atoi( s_token ) != pMesh->numFaces )
  643.         {
  644.             Error( "MESH_NUMTVFACES != MESH_NUMFACES" );
  645.         }
  646.     }
  647.     else if ( !strcmp( token, "*MESH_NUMTVERTEX" ) )
  648.     {
  649.         ASE_GetToken( qfalse );
  650.  
  651.         pMesh->numTVertexes = atoi( s_token );
  652.         VERBOSE( ( ".....num tvertexes: %d\n", pMesh->numTVertexes ) );
  653.     }
  654.     else if ( !strcmp( token, "*MESH_VERTEX_LIST" ) )
  655.     {
  656.         pMesh->vertexes = calloc( sizeof( aseVertex_t ) * pMesh->numVertexes, 1 );
  657.         pMesh->currentVertex = 0;
  658.         VERBOSE( ( ".....parsing MESH_VERTEX_LIST\n" ) );
  659.         ASE_ParseBracedBlock( ASE_KeyMESH_VERTEX_LIST );
  660.     }
  661.     else if ( !strcmp( token, "*MESH_TVERTLIST" ) )
  662.     {
  663.         pMesh->currentVertex = 0;
  664.         pMesh->tvertexes = calloc( sizeof( aseTVertex_t ) * pMesh->numTVertexes, 1 );
  665.         VERBOSE( ( ".....parsing MESH_TVERTLIST\n" ) );
  666.         ASE_ParseBracedBlock( ASE_KeyMESH_TVERTLIST );
  667.     }
  668.     else if ( !strcmp( token, "*MESH_FACE_LIST" ) )
  669.     {
  670.         pMesh->faces = calloc( sizeof( aseFace_t ) * pMesh->numFaces, 1 );
  671.         pMesh->currentFace = 0;
  672.         VERBOSE( ( ".....parsing MESH_FACE_LIST\n" ) );
  673.         ASE_ParseBracedBlock( ASE_KeyMESH_FACE_LIST );
  674.     }
  675.     else if ( !strcmp( token, "*MESH_TFACELIST" ) )
  676.     {
  677.         pMesh->tfaces = calloc( sizeof( aseFace_t ) * pMesh->numFaces, 1 );
  678.         pMesh->currentFace = 0;
  679.         VERBOSE( ( ".....parsing MESH_TFACE_LIST\n" ) );
  680.         ASE_ParseBracedBlock( ASE_KeyTFACE_LIST );
  681.     }
  682.     else if ( !strcmp( token, "*MESH_NORMALS" ) )
  683.     {
  684.         ASE_ParseBracedBlock( 0 );
  685.     }
  686. }
  687.  
  688. static void ASE_KeyMESH_ANIMATION( const char *token )
  689. {
  690.     aseMesh_t *pMesh = ASE_GetCurrentMesh();
  691.  
  692.     // loads a single animation frame
  693.     if ( !strcmp( token, "*MESH" ) )
  694.     {
  695.         VERBOSE( ( "...found MESH\n" ) );
  696.         assert( pMesh->faces == 0 );
  697.         assert( pMesh->vertexes == 0 );
  698.         assert( pMesh->tvertexes == 0 );
  699.         memset( pMesh, 0, sizeof( *pMesh ) );
  700.  
  701.         ASE_ParseBracedBlock( ASE_KeyMESH );
  702.  
  703.         if ( ++ase.objects[ase.currentObject].anim.currentFrame == MAX_ASE_ANIMATION_FRAMES )
  704.         {
  705.             Error( "Too many animation frames" );
  706.         }
  707.     }
  708.     else
  709.     {
  710.         Error( "Unknown token '%s' while parsing MESH_ANIMATION", token );
  711.     }
  712. }
  713.  
  714. static void ASE_KeyGEOMOBJECT( const char *token )
  715. {
  716.     if ( !strcmp( token, "*NODE_NAME" ) )
  717.     {
  718.         char *name = ase.objects[ase.currentObject].name;
  719.  
  720.         ASE_GetToken( qtrue );
  721.         VERBOSE( ( " %s\n", s_token ) );
  722.         strcpy( ase.objects[ase.currentObject].name, s_token + 1 );
  723.         if ( strchr( ase.objects[ase.currentObject].name, '"' ) )
  724.             *strchr( ase.objects[ase.currentObject].name, '"' ) = 0;
  725.  
  726.         if ( strstr( name, "tag" ) == name )
  727.         {
  728.             while ( strchr( name, '_' ) != strrchr( name, '_' ) )
  729.             {
  730.                 *strrchr( name, '_' ) = 0;
  731.             }
  732.             while ( strrchr( name, ' ' ) )
  733.             {
  734.                 *strrchr( name, ' ' ) = 0;
  735.             }
  736.         }
  737.     }
  738.     else if ( !strcmp( token, "*NODE_PARENT" ) )
  739.     {
  740.         ASE_SkipRestOfLine();
  741.     }
  742.     // ignore unused data blocks
  743.     else if ( !strcmp( token, "*NODE_TM" ) ||
  744.               !strcmp( token, "*TM_ANIMATION" ) )
  745.     {
  746.         ASE_ParseBracedBlock( 0 );
  747.     }
  748.     // ignore regular meshes that aren't part of animation
  749.     else if ( !strcmp( token, "*MESH" ) && !ase.grabAnims )
  750.     {
  751. /*
  752.         if ( strstr( ase.objects[ase.currentObject].name, "tag_" ) == ase.objects[ase.currentObject].name ) 
  753.         {
  754.             s_forceStaticMesh = true;
  755.             ASE_ParseBracedBlock( ASE_KeyMESH );
  756.             s_forceStaticMesh = false;
  757.         }
  758. */
  759.         ASE_ParseBracedBlock( ASE_KeyMESH );
  760.         if ( ++ase.objects[ase.currentObject].anim.currentFrame == MAX_ASE_ANIMATION_FRAMES )
  761.         {
  762.             Error( "Too many animation frames" );
  763.         }
  764.         ase.objects[ase.currentObject].anim.numFrames = ase.objects[ase.currentObject].anim.currentFrame;
  765.         ase.objects[ase.currentObject].numAnimations++;
  766. /*
  767.         // ignore meshes that aren't part of animations if this object isn't a 
  768.         // a tag
  769.         else
  770.         {
  771.             ASE_ParseBracedBlock( 0 );
  772.         }
  773. */
  774.     }
  775.     // according to spec these are obsolete
  776.     else if ( !strcmp( token, "*MATERIAL_REF" ) )
  777.     {
  778.         ASE_GetToken( qfalse );
  779.  
  780.         ase.objects[ase.currentObject].materialRef = atoi( s_token );
  781.     }
  782.     // loads a sequence of animation frames
  783.     else if ( !strcmp( token, "*MESH_ANIMATION" ) )
  784.     {
  785.         if ( ase.grabAnims )
  786.         {
  787.             VERBOSE( ( "..found MESH_ANIMATION\n" ) );
  788.  
  789.             if ( ase.objects[ase.currentObject].numAnimations )
  790.             {
  791.                 Error( "Multiple MESH_ANIMATIONS within a single GEOM_OBJECT" );
  792.             }
  793.             ASE_ParseBracedBlock( ASE_KeyMESH_ANIMATION );
  794.             ase.objects[ase.currentObject].anim.numFrames = ase.objects[ase.currentObject].anim.currentFrame;
  795.             ase.objects[ase.currentObject].numAnimations++;
  796.         }
  797.         else
  798.         {
  799.             ASE_SkipEnclosingBraces();
  800.         }
  801.     }
  802.     // skip unused info
  803.     else if ( !strcmp( token, "*PROP_MOTIONBLUR" ) ||
  804.               !strcmp( token, "*PROP_CASTSHADOW" ) ||
  805.               !strcmp( token, "*PROP_RECVSHADOW" ) )
  806.     {
  807.         ASE_SkipRestOfLine();
  808.     }
  809. }
  810.  
  811. static void ConcatenateObjects( aseGeomObject_t *pObjA, aseGeomObject_t *pObjB )
  812. {
  813. }
  814.  
  815. static void CollapseObjects( void )
  816. {
  817.     int i;
  818.     int numObjects = ase.currentObject;
  819.  
  820.     for ( i = 0; i < numObjects; i++ )
  821.     {
  822.         int j;
  823.  
  824.         // skip tags
  825.         if ( strstr( ase.objects[i].name, "tag" ) == ase.objects[i].name )
  826.         {
  827.             continue;
  828.         }
  829.  
  830.         if ( !ase.objects[i].numAnimations )
  831.         {
  832.             continue;
  833.         }
  834.  
  835.         for ( j = i + 1; j < numObjects; j++ )
  836.         {
  837.             if ( strstr( ase.objects[j].name, "tag" ) == ase.objects[j].name )
  838.             {
  839.                 continue;
  840.             }
  841.             if ( ase.objects[i].materialRef == ase.objects[j].materialRef )
  842.             {
  843.                 if ( ase.objects[j].numAnimations )
  844.                 {
  845.                     ConcatenateObjects( &ase.objects[i], &ase.objects[j] );
  846.                 }
  847.             }
  848.         }
  849.     }
  850. }
  851.  
  852. /*
  853. ** ASE_Process
  854. */
  855. static void ASE_Process( void )
  856. {
  857.     while ( ASE_GetToken( qfalse ) )
  858.     {
  859.         if ( !strcmp( s_token, "*3DSMAX_ASCIIEXPORT" ) ||
  860.              !strcmp( s_token, "*COMMENT" ) )
  861.         {
  862.             ASE_SkipRestOfLine();
  863.         }
  864.         else if ( !strcmp( s_token, "*SCENE" ) )
  865.             ASE_SkipEnclosingBraces();
  866.         else if ( !strcmp( s_token, "*MATERIAL_LIST" ) )
  867.         {
  868.             VERBOSE( ("MATERIAL_LIST\n") );
  869.  
  870.             ASE_ParseBracedBlock( ASE_KeyMATERIAL_LIST );
  871.         }
  872.         else if ( !strcmp( s_token, "*GEOMOBJECT" ) )
  873.         {
  874.             VERBOSE( ("GEOMOBJECT" ) );
  875.  
  876.             ASE_ParseBracedBlock( ASE_KeyGEOMOBJECT );
  877.  
  878.             if ( strstr( ase.objects[ase.currentObject].name, "Bip" ) ||
  879.                  strstr( ase.objects[ase.currentObject].name, "ignore_" ) )
  880.             {
  881.                 ASE_FreeGeomObject( ase.currentObject );
  882.                 VERBOSE( ( "(discarding BIP/ignore object)\n" ) );
  883.             }
  884.             else if ( ( strstr( ase.objects[ase.currentObject].name, "h_" ) != ase.objects[ase.currentObject].name ) &&
  885.                       ( strstr( ase.objects[ase.currentObject].name, "l_" ) != ase.objects[ase.currentObject].name ) &&
  886.                       ( strstr( ase.objects[ase.currentObject].name, "u_" ) != ase.objects[ase.currentObject].name ) &&
  887.                       ( strstr( ase.objects[ase.currentObject].name, "tag" ) != ase.objects[ase.currentObject].name ) &&
  888.                       ase.grabAnims )
  889.             {
  890.                 VERBOSE( ( "(ignoring improperly labeled object '%s')\n", ase.objects[ase.currentObject].name ) );
  891.                 ASE_FreeGeomObject( ase.currentObject );
  892.             }
  893.             else
  894.             {
  895.                 if ( ++ase.currentObject == MAX_ASE_OBJECTS )
  896.                 {
  897.                     Error( "Too many GEOMOBJECTs" );
  898.                 }
  899.             }
  900.         }
  901.         else if ( s_token[0] )
  902.         {
  903.             printf( "Unknown token '%s'\n", s_token );
  904.         }
  905.     }
  906.  
  907.     if ( !ase.currentObject )
  908.         Error( "No animation data!" );
  909.  
  910.     CollapseObjects();
  911. }
  912.  
  913.